package br.unifor.cct.mia.evolutionary;

import br.unifor.cct.mia.util.Configurations;
import br.unifor.cct.mia.util.Methods;


public class Genotype extends Individual {

	private static final long serialVersionUID = -3462541438659053204L;	
	protected double[] gene, upper, lower;
	protected boolean[] integer;

	public int hashCode() {
		int hashCode = 0;
		int atual = 3;
		for ( int i=0; i<gene.length; i++ ) {
			hashCode += gene[i]*Methods.gerarPrimo(atual);
			atual++;
		}		
		return hashCode;
	}
	
	public boolean equals(Object arg0) {
		Genotype gen = (Genotype)arg0;

		for ( int i=0; i<lower.length; i++ ) {
			if ( gen.getLower()[i] != lower[i] ) 
				return false;
		}
		
		for ( int i=0; i<upper.length; i++ ) {
			if ( gen.getUpper()[i] != upper[i] ) 
				return false;
		}
		
		for ( int i=0; i<integer.length; i++ ) {
			if ( gen.getInteger()[i] != integer[i] ) 
				return false;
		}
		
		for ( int i=0; i<gene.length; i++ ) {
			if ( gen.getGene()[i] != gene[i] ) 
				return false;
		}
		return true;
	}
	
	public Genotype(Configurations c){
		this.configurations = c;
		gene = new double[c.getNvars()];
		lower = new double[c.getNvars()];
		upper = new double[c.getNvars()];
		integer = new boolean[c.getNvars()];
	}
	
	public Object clone() {
		Genotype result = new Genotype(configurations);
		result.setFitness(this.getFitness());
		result.setSpeciesCount(this.getSpeciesCount());
		result.setSelectProbability(this.getSelectProbability());
		result.setLower(this.getLower());
		result.setUpper(this.getUpper());
	    System.arraycopy(this.getGene(),0,result.getGene(),0,this.getGene().length);
	    System.arraycopy(this.getInteger(),0,result.getInteger(),0,this.getInteger().length);
		return result;
	}
	
	public String toString(){
		String genes = "";
		
		for(int i = 0; i < configurations.getNvars(); i++) 
			genes += gene[i]+"  ";
		
		return  "fitness = "+fitness+"\n" +
				"probabilty = "+selectProbability+"\n"+
				"genes = "+genes;
	}
		
	public double[] getGene() {
		return gene;
	}
	public void setGene(double[] gene) {
		this.gene = gene;
	}
	public void setGene(double gene, int pos) {
		this.gene[pos] = gene;
	}
	public double getGene(int i) {
		return gene[i];
	}	
    public void setLower(double[] lower) {
        this.lower = lower;
    }
    public void setLower(double lower, int pos) {
        this.lower[pos] = lower;
    }
    public double[] getLower() {
        return this.lower;
    }
    public double getLower(int pos) {
        return this.lower[pos];
    }    
	public void setUpper(double[] upper) {
        this.upper = upper;
    }
    public void setUpper(double upper, int pos) {
        this.upper[pos] = upper;
    }
    public double[] getUpper() {
        return this.upper;
    }
    public double getUpper(int pos) {
        return this.upper[pos];
    }
    public void setInteger(boolean[] integer) {
        this.integer = integer;
    }
    public void setInteger(boolean integer, int pos) {
        this.integer[pos] = integer;
    }
    public boolean[] getInteger() {
        return this.integer;
    }
    public boolean getInteger(int pos) {
        return this.integer[pos];
    }
    
    public double getFitnessMin() {
		return -getFitness();
	}
}